home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume6 / newbatcha < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  30.9 KB

  1. Subject: v06i052:  Usenet news batcher control program (newbatchA)
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: cca!caip!cbmvax!bpa!espo (Bob Esposito)
  6. Mod.sources: Volume 6, Issue 52
  7. Archive-name: newbatchA
  8.  
  9. [  This is the first of two batched news utility programs (BNUP, to coin
  10.    an acronym).  It was written on a SystemV machine, but it looks like
  11.    it would be fairly easy to convert to BSD and, e.g., the directory
  12.    library.  Stuff dealing with the UUCP queue is much less portable,
  13.    of course, but Bob nicely provides a default mechanism.  Take a look
  14.    at the check_uucp routine, however -- I think you may want a different
  15.    default value.  Also, I added a modified xerror routine that doesn't
  16.    depend on knowing the internal's of the FILE struct.  I haven't
  17.    tested it, but a "grep xerror *." seems to say I'm ok; add -DUSE_PORT_CODE
  18.    for my version.  --r$ ]
  19.  
  20. #!/bin/sh
  21. # This is a shell archive.  Remove anything before this line,
  22. # then unpack it by saving it in a file and typing "sh file".
  23. # Contents:  README nbatcher.1 nbatcher.ctl nbatcher.doc Makefile
  24. #    bst.c checkwork.c define.c logger.c main.c nbatcher.c parse.c
  25.  
  26. echo x - README
  27. sed 's/^XX//' > "README" <<'@//E*O*F README//'
  28. XXThe program provides a better way to handling batching of USENET news
  29. XXto neighboring sites.  It works with 2.10B and later, including
  30. XX2.10.3B, which provides compression batching.
  31.  
  32. XXPlease send any questions and bug reports to me (bpa!espo) for
  33. XXdistribution to the net.  This software is public domain, and cannot be
  34. XXsold for any profit.
  35.  
  36. XXNbatcher was written for UNIX (trademark of AT&T) System V, but should
  37. XXbe compatible with most version currently being used today.  It is
  38. XXpresently running on a VAX (trademark of DEC) 11/780 feeding 5 remote
  39. XXsites with news.  Two important issues MUST be noted here.
  40.  
  41. XXSince nbatcher checks the UUCP directory for each site listed in the
  42. XXcontrol file, directory configuration should be UUCPDIR/sitename, e.g.
  43. XX/usr/spool/uucp/foo for site foo.  But since not everyone is generic,
  44. XXI've allowed nbatcher to skip over the UUCP byte counting routine if
  45. XXthis is not so.  In addition to this, some uucpcleanup daemons remove
  46. XXthe site directory if there's nothing spooled there.  When this
  47. XXhappens, nbatcher will notify you of this and continue on.
  48.  
  49. XXThe other issue is that you MUST configure your NEWSLIB/sys file using the
  50. XXbatch syntax as described in the USENET Installation document.  Field 3
  51. XXshould contain the `F' flag indicating a batched transmission for that
  52. XXsite and field 4 should contain the filename where news article's full
  53. XXpathname will be appended to.  Nbatcher requires that the filename in
  54. XXfield 4 match the sitename in the control file.  For example, the entry:
  55. XX    foo:net,mod,usa,na,to.foo:F:/usr/spool/batchnews/foo
  56. XXsays that all news articles going to site `foo' will be batched, using
  57. XXthe file `foo' in /usr/spool/batchnews.  Nbatcher's control file entry:
  58. XX    foo:3,14,22:16:150000:
  59. XXwill get the news article's full pathname from /usr/spool/batchnews/foo
  60. XXfor batching.  This requirement MUST be adhered to for nbatcher to work
  61. XXcorrectly.  I believe most sites that batch news use this type of
  62. XXconfiguration, since its easy to keep track of a remote site's work.
  63. XXNote that the name of the directory "/usr/spool/batchnews" is set
  64. XXin the Makefile.
  65.  
  66. XXThe manual page describes the control file, as does nbatcher.doc.  Note
  67. XXthat even though nbatcher indicates max bytes has been reached, if that
  68. XXsite gets compressed batches, the next time nbatcher runs for that site
  69. XXwork could get scheduled.
  70.  
  71. XXAlso included is a utility program called "bst," BatchSTatus, which
  72. XXshows who many news articles are currently in the batch file for each
  73. XXsystem.  Just type "make bst" for that and copy it to where you want,
  74. XXusually LIBDIR.  Note that bst does reads on the directory structure
  75. XXdirectly.
  76.  
  77. XXInstallation is simple:  look at the first few #define's in nbatcher.h;
  78. XXalso edit the Makefile for the appropriate BATCHDIR and LIBDIR for your
  79. XXsite.  Type "make" or "make install."
  80.  
  81. XXNOTE:  Read the comments in parse.c concerning MAX_BYTES.  This is the
  82. XXmaximum amount of bytes per site that's allowed in the control file for
  83. XXqueue_size.  Change it at your own risk!
  84.  
  85. XX    Bob Esposito
  86. XX    bpa!espo
  87. XX    Bell of Penna.
  88. @//E*O*F README//
  89. chmod u=rw,g=rw,o=rw README
  90.  
  91. echo x - nbatcher.1
  92. sed 's/^XX//' > "nbatcher.1" <<'@//E*O*F nbatcher.1//'
  93. XX.TH NBATCHER 1 LOCAL
  94. XX.SH NAME
  95. XXnbatcher  \- new batching system for news
  96. XX.SH SYNOPSIS
  97. XX.B nbatcher
  98. XX.IR "(run out of " cron ".)"
  99. XX.SH DESCRIPTION
  100. XX.PP
  101. XX.I Nbatcher
  102. XXis a program designed to send batched USENET data out in an orderly and
  103. XXcontrolled fashion, while providing alternative transmission methods.
  104. XXAs such, it is a replacement for
  105. XX.I csendbatch
  106. XXand the like, which typically require many entries in
  107. XX.IR crontab .
  108. XX.I Nbatcher
  109. XXis intended to be run hourly out of
  110. XX.I cron
  111. XXas the USENET administrator (NEWSID).
  112. XX.PP
  113. XX.I Nbatcher
  114. XXscans the file
  115. XX.I nbatcher.ctl
  116. XXin the NEWSLIB directory to determine if work should be spooled for a system.
  117. XXIn the control file, lines starting with asterisks are ignored; data lines
  118. XXare comprised of five colon\-separated fields:
  119. XX.RS
  120. XXsite:hour:bits:queue_size:command
  121. XX.RE
  122. XX.TP ``site''
  123. XXName of the USENET neighbor; it is the same as the site in the news
  124. XX.I sys
  125. XXfile.
  126. XX.TP ``hours''
  127. XXThis field is patterned after
  128. XX.IR cron 's.
  129. XXIf the hour is ``off,'' no work is spooled for the site.
  130. XXAn hour of ``*'' matches every hour.
  131. XXIt is also possible to specify specific hours, (e.g., 8, 09, or 22), a
  132. XXcomma\-separated list (e.g., 8,09,22), or a twenty\-four range, like
  133. XX1-\15 for 10am through 3pm and 22\-4, for 10pm through 4am.
  134. XX.TP ``bits''
  135. XXThis field specifies the number of bits to use in compression; it should be
  136. XXa number between nine and 16, inclusive, or null.
  137. XXIf a number is specified, it is passed on to the
  138. XX.I compress
  139. XXprogram via the ``\-b'' flag.
  140. XX.TP ``queue_size''
  141. XXThis field specifies the maximum number of bytes allowed in the UUCP queue
  142. XXfor this site.
  143. XXThe default is 100K.
  144. XXThe UUCP queue size is determined by looking in the
  145. XX.IR /usr/spool/uucp/ site
  146. XXdirectory; if it doesn't exist, the check is bypassed.
  147. XXIf there is data in the UUCP queue,
  148. XX.I nbatcher
  149. XXwill only queue up as many USENET transfers as will fit within the limit
  150. XXspecified by the ``queue_size'' field.
  151. XX.TP ``command''
  152. XXThis field is used to specific the UUCP command that should be used to queue
  153. XXthe job; as distributed, the default is ``uux \- \-r site!rnews''; note the
  154. XXabsence of the ``\-z'' flag.
  155. XX.PP
  156. XXTo set up a USENET neighbor to be controlled by
  157. XX.IR nbatcher ,
  158. XXthe news
  159. XX.I sys
  160. XXentry for the neighbor must be modified to specify the ``F'' flag, and the
  161. XXfile used to contain the article names must be
  162. XX.RI BATCHDIR/sysname ,
  163. XXwhere BATCHDIR is set in the Makefile as distributed.
  164. XX.SH FILES
  165. XX.TP NEWSLIB/nbatcher.log
  166. XXA logfile of failures, postponements, etc.
  167. XX.SH BUGS
  168. XXParsing of the control file is fairly robust, but not perfect.
  169. @//E*O*F nbatcher.1//
  170. chmod u=rw,g=rw,o=rw nbatcher.1
  171.  
  172. echo x - nbatcher.ctl
  173. sed 's/^XX//' > "nbatcher.ctl" <<'@//E*O*F nbatcher.ctl//'
  174. XX*
  175. XX*    NBATCHER.CTL
  176. XX*    Edit and install in your NEWSLIB directory.
  177. XX*
  178. XX*  Comments start with *; data lines look like:
  179. XX*    site:hours:bits:queue_size:command
  180. XX*  Where
  181. XX*    site        = name of the remote site
  182. XX*    hour        = when to do work (* is all, off is never, 22-4 is ok)
  183. XX*    bits        = passed on to compress via -b; null gets default
  184. XX*    queue_size    = Max # bytes allowed in UUCP queue before postponing
  185. XX*    command        = optional command line
  186. XX*
  187. XX*  See manpage and README for more info.
  188. @//E*O*F nbatcher.ctl//
  189. chmod u=rw,g=rw,o=rw nbatcher.ctl
  190.  
  191. echo x - nbatcher.doc
  192. sed 's/^XX//' > "nbatcher.doc" <<'@//E*O*F nbatcher.doc//'
  193.  
  194. XXDETAILED DESCRIPTION OF "NBATCHER.CTL" FILE
  195. XX-------------------------------------------
  196.  
  197. XXAs distributed, nbatcher.ctl contains just a terse summary of its
  198. XXformat.  For each site you feed news to, providing that site uses the
  199. XX":F:BATCHDIR/site" batching syntax in the sys file, a corresponding
  200. XXentry should exist in nbatcher.ctl  Each line is a five-field,
  201. XXcolon-separated entry indicating what to do for that site.  The default
  202. XXfor BATCHDIR is /usr/spool/batchnews.
  203.  
  204. XXThe format is:
  205. XX    site:hour:bits:queue_size:command
  206. XXThe site field is the name of the UUCP site that will get the batched
  207. XXnews.  There MUST be a file in the BATCHDIR directory with the
  208. XXsitename.  Nbatcher will complain about mismatches.  This file contains
  209. XXa full-path listing of the files to batch.
  210.  
  211. XXNext is the hour field.  The syntax directly imitates the crontab entry
  212. XXfor hour.  If hour = "*", than assume a match for every hour.  If hour
  213. XX= "off", then no work is ever spooled for this site.  (This is the only
  214. XXdifference from crontab).  You can specify a specific hour, like 8 or
  215. XX09 or 22.  Or a range of hours, like 10-15, meaning check for work from
  216. XX10am thru 3pm.  You can also cycle thru a 24-hour period by saying
  217. XX22-4, which matches for 10pm thru 4am.  Also, hours comma separated
  218. XXlike 7,14,21, says check for work at 7 AM, 4PM and 9PM only.  This
  219. XXgives lots of flexibility for sites that feed multiple remotes.
  220.  
  221. XXNext is the bits field, which has a value of 9-16, or may be left blank.
  222. XXIf non-null, this field is directly passed on to compress with the -b
  223. XXflag.  If it is null, then no compression is done for this site.
  224.  
  225. XXThe queue_size field is the maximum number of bytes allowed on the UUCP
  226. XXqueue at any time.  It defaults to 100K bytes, and if it's greater than
  227. XX1MB (see parse.c about MAX_BYTES), than it uses 1MB as the default
  228. XXnumber of bytes.
  229.  
  230. XXWhat nbatcher does is first check the UUCPDIR for that site and sums up
  231. XXthe number of bytes already on-queue.  The size of each news article is
  232. XXaccumulated prior to batching to the tempfile, and this accumulation +
  233. XXthe UUCP on-queue bytes are checked to see if they surpass the queue_size
  234. XXvalue.  If not, things proceed normally.  But if it would exceed the
  235. XXmax value, then spool what's already been batched, and save the
  236. XXremainder of the articles for the next scheduled batch.
  237.  
  238. XXThis is so noted in the nbatcher.log file, showing the UUCP bytes that
  239. XXwere on-queue (if any), and the number of bytes that were spooled.
  240. XXAlso, if nbatcher is run from a terminal instead of from cron, a copy
  241. XXof what gets logged is sent to the terminal.
  242.  
  243. XXThe last field is the command field.  This optional field is used for
  244. XXspecific UUCP command execution.  As written, it defaults to "uux - -r
  245. XXsite!rnews".  Since my uux doesn't require the -z option for rnews, I
  246. XXleft it out of the UUX define in nbatcher.h  This can easily be changed
  247. XXfor your own taste, or just use the command field.
  248.  
  249. XXExample:
  250. XX    site-A:3,10:16:450000:
  251. XXCheck for work for site-A at 3AM and 10AM.  Use compress with
  252. XX16 bits and only spool up to 450K bytes, using "uux - -r site-A!rnews".
  253.  
  254. XXAnother example:
  255. XX    foo:23-4::300000:uux - -r -z foo!rnews
  256. XXCheck for work for foo between 11PM and 4AM.  No compression is used
  257. XXand spool up to 300K bytes using the command field.
  258.  
  259. XXThis format should help ease UUCP congestion on the local site for
  260. XXnews.  I currently feed 5 remote sites, compressed and non-compressed
  261. XXformats, and have noticed a vast improvement in disk space as well as
  262. XXout port availability for UUCP.  It has allowed me to check for work
  263. XXfor all sites every hour, since there's a limit on how much gets
  264. XXqueued.  And if the remote doesn't answer on the hourly UUCP poll, so
  265. XXwhat!  Nbatcher just won't spool any more until the queue_size limit
  266. XXon-queue is reduced.
  267.  
  268. XXNbatcher was designed to weed out any illegal syntax in the control
  269. XXfile, but it's not bug-proof, so use some discretion.
  270.  
  271. XXBob Esposito
  272. XXBell of Penna.
  273. XXJune 1986
  274. @//E*O*F nbatcher.doc//
  275. chmod u=rw,g=rw,o=rw nbatcher.doc
  276.  
  277. echo x - Makefile
  278. sed 's/^XX//' > "Makefile" <<'@//E*O*F Makefile//'
  279. XX#
  280. XX#    Makefile for nbatcher
  281. XX#
  282. XX#    R.J. Esposito
  283. XX#    Bell of Penna.
  284. XX#    June 1986
  285. XX#
  286.  
  287. XX#    You MUST define BATCHDIR as the place where USENET
  288. XX#    puts the articles to be batched.
  289. XX#
  290. XX#    LIBDIR is where you USENET library is and also
  291. XX#    MUST be defined.
  292.  
  293. XXBATCHDIR = /usr/spool/batchnews
  294. XXLIBDIR = /misc/lib/usenet
  295.  
  296. XXCFLAGS = -O -c
  297. XXLFLAGS = -s
  298. XXDFLAGS = -DBATCHDIR='"$(BATCHDIR)"' -DLIBDIR='"$(LIBDIR)"'
  299.  
  300. XXOBJS = define.o main.o parse.o checkwork.o nbatcher.o logger.o
  301.  
  302. XXSRC = define.c main.c parse.c checkwork.c nbatcher.c logger.c nbatcher.h bst.c
  303. XXDOCS = README nbatcher.ctl nbatcher.doc
  304.  
  305. XXall: $(OBJS)
  306. XX    $(CC) $(DFLAGS) $(LFLAGS) -o nbatcher $(OBJS)
  307. XX    chmod 0755 nbatcher
  308.  
  309. XXinstall: all
  310. XX    cp nbatcher $(LIBDIR)
  311. XX    chmod 0755 $(LIBDIR)/nbatcher
  312. XX    cp nbatcher.ctl $(LIBDIR)/nbatcher.ctl
  313. XX    chmod 0644 $(LIBDIR)/nbatcher.ctl
  314.  
  315. XXdefine.o: nbatcher.h define.c
  316. XX    $(CC) $(CFLAGS) $(DFLAGS) define.c
  317.  
  318. XXmain.o: nbatcher.h main.c
  319. XX    $(CC) $(CFLAGS) $(DFLAGS) main.c
  320.  
  321. XXparse.o: nbatcher.h parse.c
  322. XX    $(CC) $(CFLAGS) $(DFLAGS) parse.c
  323.  
  324. XXcheckwork.o: nbatcher.h checkwork.c
  325. XX    $(CC) $(CFLAGS) $(DFLAGS) checkwork.c
  326.  
  327. XXnbatcher.o: nbatcher.h nbatcher.c
  328. XX    $(CC) $(CFLAGS) $(DFLAGS) nbatcher.c
  329.  
  330. XXlogger.o: nbatcher.h logger.c
  331. XX    $(CC) $(CFLAGS) $(DFLAGS) logger.c
  332.  
  333. XXbst: bst.c
  334. XX    $(CC) $(CFLAGS) $(DFLAGS) bst.c
  335. XX    $(CC) $(LFLAGS) -o bst bst.o
  336.  
  337. XXclean:
  338. XX    rm -f *.o *.shar
  339.  
  340. XXclobber: clean
  341. XX    rm -f nbatcher
  342.  
  343.  
  344. XXshar:
  345. XX    shar -v $(SRC) $(DOCS) Makefile > nbatcher.shar
  346. @//E*O*F Makefile//
  347. chmod u=rw,g=rw,o=rw Makefile
  348.  
  349. echo x - bst.c
  350. sed 's/^XX//' > "bst.c" <<'@//E*O*F bst.c//'
  351. XX/*
  352. XX *    bst.c - a utility for indicating how many
  353. XX *        news articles are ready for batching
  354. XX *        for each site in the BACTHDIR directory.
  355. XX *
  356. XX *    R.J. Esposito
  357. XX *    Bell of Penna.
  358. XX *    June 1986
  359. XX *
  360. XX */
  361.  
  362. XX#include <stdio.h>
  363. XX#include <sys/types.h>
  364. XX#include <sys/stat.h>
  365. XX#include <sys/dir.h>
  366.  
  367.  
  368. XXchar buf[512];
  369. XXFILE *dd;
  370. XXstruct direct dp;
  371. XXstruct stat st;
  372.  
  373. XXmain()
  374. XX{
  375. XX    int fd, j;
  376. XX    int bcnt, lcnt;
  377.  
  378. XX    if(chdir(BATCHDIR) != 0) {
  379. XX        perror(BATCHDIR);
  380. XX        exit(1);
  381. XX    }
  382.  
  383. XX    if((dd=fopen(".", "r")) == NULL) {
  384. XX        printf("can't open %s\n", BATCHDIR);
  385. XX        exit(1);
  386. XX    }
  387.  
  388. XX    while((fread((char *)&dp, sizeof(dp), 1, dd)) == 1) {
  389. XX        if(dp.d_ino == 0 || dp.d_name[0] == '.')
  390. XX            continue;
  391. XX        if(stat(dp.d_name, &st) != 0) {
  392. XX            printf("can't stat %s\n", dp.d_name);
  393. XX            exit(1);
  394. XX        }
  395. XX        if(st.st_size <= 0 )
  396. XX            continue;
  397. XX        if((fd=open(dp.d_name, 0)) < 0) {
  398. XX            printf("can't open %s\n", dp.d_name);
  399. XX            exit(1);
  400. XX        }
  401. XX        lcnt = 0;
  402. XX        while((bcnt=read(fd,buf,512)) > 0) {
  403. XX            for(j=0; j<=bcnt; j++)
  404. XX                if(buf[j] == '\n')
  405. XX                    lcnt += 1;
  406. XX        }
  407. XX        close(fd);
  408. XX        printf("%s\t  %d article", dp.d_name, lcnt);
  409. XX        printf("%c\n", lcnt > 1 ? 's' : ' ');
  410. XX    }
  411. XX}
  412. @//E*O*F bst.c//
  413. chmod u=rw,g=rw,o=rw bst.c
  414.  
  415. echo x - checkwork.c
  416. sed 's/^XX//' > "checkwork.c" <<'@//E*O*F checkwork.c//'
  417. XX/*
  418. XX *
  419. XX *    checkwork.c - look to see if there's any work
  420. XX *              to do for a site.
  421. XX *
  422. XX *    R.J. Esposito
  423. XX *    Bell of Penna.
  424. XX *    June 1986
  425. XX *
  426. XX */
  427.  
  428. XX#include <stdio.h>
  429. XX#include <sys/types.h>
  430. XX#include <sys/stat.h>
  431. XX#include <sys/utsname.h>
  432. XX#include <sys/dir.h>
  433. XX#include <ctype.h>
  434. XX#include <time.h>
  435. XX#include "nbatcher.h"
  436.  
  437. XXwork_to_do ()
  438. XX{
  439. XX    register char    *p;
  440. XX    struct tm    *localtime(), *tp;
  441. XX    struct stat    st;
  442. XX    char    buf[BUFSIZ];
  443. XX    long    time(), clock;
  444. XX    int    hour;
  445. XX    short    num, upper, lower;
  446.  
  447. XX    sprintf (buf, "%s/%s", BATCHDIR, ep.site);
  448.  
  449. XX    if (stat(buf, &st) < 0)
  450. XX        xerror ("bad stat on %s\n", buf);
  451.  
  452. XX    /* if the size of the batch file is
  453. XX       zero, return FALSE
  454. XX    */
  455.  
  456. XX    if (st.st_size == 0)
  457. XX        return (FALSE);
  458.  
  459. XX    /* now see if it time to do anything */
  460.  
  461. XX    clock = time ((long *)0);
  462. XX    tp = localtime (&clock);
  463. XX    hour = tp->tm_hour;
  464.  
  465. XX    p = (char *) ep.hour;
  466.  
  467. XX    if (*p == '*')        /* match any hour */
  468. XX        return (check_uucp());
  469.  
  470. XX    if (strncmp(p, "off", 3) == 0)    /* just what it says, off */
  471. XX        return (FALSE);
  472.  
  473. XX    /* parse thru hour field to see if
  474. XX       this is the hour to do work */
  475.  
  476. XX    num = 0;
  477. XX    do {
  478. XX        num = num*10 + (*p - '0');
  479. XX    } while (isdigit(*++p));
  480. XX    if (num == hour)
  481. XX        return (check_uucp());
  482.  
  483. XX    if (*p == '-') {
  484. XX        lower = num;
  485. XX        p++;
  486. XX        num = 0;
  487. XX        do {
  488. XX            num = num*10 + (*p - '0');
  489. XX        } while (isdigit(*++p));
  490. XX        upper = num;
  491.  
  492. XX        if (lower < upper) {    /* normal hour range */
  493. XX            if (hour >= lower && hour <= upper)
  494. XX                return (check_uucp());
  495. XX        } else if (lower > upper) {    /* 24 hr. cycle thru */
  496. XX            if (hour >= lower || hour <= upper)
  497. XX                return (TRUE);
  498. XX        } else
  499. XX            return (FALSE);
  500. XX    }
  501.  
  502. XX    if (*p == ',') {
  503. XX        p++;
  504. XX        while (*p) {
  505. XX            num = 0;
  506. XX            do {
  507. XX                num = num*10 + (*p - '0');
  508. XX            } while (isdigit(*++p));
  509. XX            if (num == hour)
  510. XX                return (check_uucp());
  511. XX            p++;
  512. XX        }
  513. XX    }
  514.  
  515. XX    return (FALSE);
  516. XX}
  517.  
  518. XX/*    If check_uucp cannot find the remote site
  519. XX *    directory, just bypass the byte counting
  520. XX *    routine.  This is necessary because the
  521. XX *    uucpcleanup daemon, on some sites, removes
  522. XX *    the site directory when there's nothing there.
  523. XX */
  524.  
  525. XXcheck_uucp()
  526. XX{
  527. XX    struct utsname    utsn;
  528. XX    struct direct    dp;
  529. XX    struct stat    st;
  530. XX    FILE    *dfp;
  531. XX    char    u_name[9], buf[80];
  532. XX    short    prefix_len;
  533.  
  534. XX    if (uname(&utsn) < 0)
  535. XX        xerror ("can't get local nodename\n");
  536.  
  537. XX    sprintf (buf, "%s/%s", UUCPDIR, ep.site);
  538. XX    if (chdir(buf) < 0) {
  539. XX       fprintf (stderr, "nbatcher: can't chdir to %s - bypassing UUCP check\n", buf);
  540. XX       return (TRUE);
  541. XX    }
  542.  
  543. XX    if ((dfp=fopen(".", "r")) == NULL) {
  544. XX       fprintf (stderr, "nbatcher: fopen error on %s - bypassing UUCP check\n", UUCPDIR);
  545. XX       return (TRUE);
  546. XX    }
  547.  
  548. XX    sprintf (buf, "D.%s", utsn.nodename);
  549. XX    prefix_len = (short) strlen(buf);
  550. XX    n_bytes = 0;
  551. XX    while ((fread((char *)&dp, sizeof(dp), 1, dfp)) == 1) {
  552. XX        if (dp.d_ino == 0 || dp.d_name[0] == '.')
  553. XX            continue;
  554. XX        if (strncmp(dp.d_name, buf, prefix_len))
  555. XX            continue;
  556. XX        if (stat(dp.d_name, &st) < 0) {
  557. XX          fprintf (stderr, "nbatcher: bad stat on UUCP_file %s - bypassing\n", dp.d_name);
  558. XX          continue;
  559. XX        }
  560. XX        n_bytes += st.st_size;
  561. XX        if (n_bytes > ep.m_bytes) {
  562. XX            fclose (dfp);
  563. XX            return (FALSE);
  564. XX        }
  565. XX    }
  566. XX    fclose (dfp);
  567. XX    if (chdir(LIBDIR) < 0)
  568. XX        xerror ("can't chdir back to %s\n", LIBDIR);
  569.  
  570. XX    return (TRUE);
  571. XX}
  572. @//E*O*F checkwork.c//
  573. chmod u=rw,g=rw,o=rw checkwork.c
  574.  
  575. echo x - define.c
  576. sed 's/^XX//' > "define.c" <<'@//E*O*F define.c//'
  577. XX/*
  578. XX *    define.c - global defines for nbatcher.
  579. XX *
  580. XX *    R.J. Esposito
  581. XX *    Bell of Penna.
  582. XX *    June 1986
  583. XX *
  584. XX */
  585.  
  586. XX#include <stdio.h>
  587. XX#include "nbatcher.h"
  588.  
  589. XXFILE    *lfp,
  590. XX    *tfp,
  591. XX    *log = NULL;
  592.  
  593. XXlong    n_bytes,
  594. XX    cu_bytes;
  595.  
  596. XXchar    *tfile = NULL;
  597.  
  598. XXshort    vflg = 0,
  599. XX    nfiles = 10;
  600.  
  601. XXint    fcnt = 0,
  602. XX    scnt = 0;
  603.  
  604. @//E*O*F define.c//
  605. chmod u=rw,g=rw,o=rw define.c
  606.  
  607. echo x - logger.c
  608. sed 's/^XX//' > "logger.c" <<'@//E*O*F logger.c//'
  609. XX/*
  610. XX *
  611. XX *    logger.c - log info about nbatcher
  612. XX *
  613. XX *    R.J. Esposito
  614. XX *    Bell of Penna.
  615. XX *    June 1986
  616. XX *
  617. XX */
  618.  
  619. XX#include <stdio.h>
  620. XX#include <time.h>
  621. XX#include "nbatcher.h"
  622.  
  623. XXlog_it (bytes)
  624. XXlong    bytes;
  625. XX{
  626. XX    struct tm    *localtime(), *tp;
  627. XX    long    time(), clock;
  628. XX    char    logfile[80], buf[BUFSIZ];
  629. XX    char    pbuf[BUFSIZ];
  630.  
  631. XX    sprintf (logfile, "%s/%s", LIBDIR, "nbatcher.log");
  632. XX    if (log == NULL) {
  633. XX        if ((log=fopen(logfile, "a")) == NULL)
  634. XX           fprintf (stderr, "can't append to logfile\n");
  635. XX    }
  636.  
  637. XX    rewind (log, 0L, 2);    /* just incase */
  638.  
  639. XX    clock = time ((long *)0);
  640. XX    tp = localtime (&clock);
  641. XX    sprintf (buf, "%.2d/%.2d %.2d:%.2d %s: %d %s batched, %d %s queued\n",
  642. XX       tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, ep.site,
  643. XX       fcnt, (fcnt==1 ? "file" : "files"), scnt,
  644. XX       (scnt==1 ? "file" : "files"));
  645.  
  646. XX    if (bytes)
  647. XX       sprintf (pbuf, "%s\tmax bytes reached.  UUCP bytes was %ld, byte count = %ld\n",
  648. XX            buf, n_bytes, bytes);
  649. XX    else
  650. XX        sprintf (pbuf, "%s", buf);
  651.  
  652. XX    if (vflg)
  653. XX        fprintf (stdout, "%s",pbuf);
  654.  
  655. XX    if (log != NULL)
  656. XX        fputs (pbuf, log);
  657.  
  658. XX}
  659. @//E*O*F logger.c//
  660. chmod u=rw,g=rw,o=rw logger.c
  661.  
  662. echo x - main.c
  663. sed 's/^XX//' > "main.c" <<'@//E*O*F main.c//'
  664. XX/*
  665. XX *
  666. XX *    main.c - for nbatcher
  667. XX *
  668. XX *    R.J. Esposito
  669. XX *    Bell of Penna.
  670. XX *    June 1986
  671. XX *
  672. XX */
  673.  
  674. XX#include <stdio.h>
  675. XX#include "nbatcher.h"
  676.  
  677. XXmain()
  678. XX{
  679. XX    int    uid;
  680. XX    FILE    *cfp;
  681. XX    char    fbuf[BUFSIZ];
  682.  
  683. XX    uid = getuid();
  684.  
  685. XX    if (uid && uid != NEWSUID)
  686. XX        xerror ("permission denied - not NEWSUSER\n");
  687.  
  688. XX    if (chdir(LIBDIR) < 0)
  689. XX        xerror ("can't chdir to %s\n", LIBDIR);
  690.  
  691. XX    if ((cfp=fopen("nbatcher.ctl", "r")) == NULL)
  692. XX        xerror ("no `batcher.ctl' file found\n");
  693.  
  694. XX    if (isatty(0))
  695. XX        vflg = TRUE;
  696.  
  697. XX    while ((fgets(fbuf, sizeof(fbuf), cfp)) != NULL) {
  698. XX        if (fbuf[0] == '*' || fbuf[0] == '\n')
  699. XX            continue;
  700. XX        parse_entry (fbuf);
  701. XX        if (!work_to_do())
  702. XX            continue;
  703. XX        batch_it ();
  704. XX    }
  705.  
  706. XX    fclose (cfp);
  707. XX    unlink (tfile);
  708. XX    exit (0);
  709. XX}
  710. XX    
  711. @//E*O*F main.c//
  712. chmod u=rw,g=rw,o=rw main.c
  713.  
  714. echo x - nbatcher.c
  715. sed 's/^XX//' > "nbatcher.c" <<'@//E*O*F nbatcher.c//'
  716. XX/*
  717. XX *
  718. XX *    nbatcher.c - where it really happens.
  719. XX *
  720. XX *    R.J. Esposito
  721. XX *    Bell of Penna.
  722. XX *    June 1986
  723. XX *
  724. XX */
  725.  
  726. XX#include <stdio.h>
  727. XX#include <sys/types.h>
  728. XX#include <sys/stat.h>
  729. XX#include <time.h>
  730. XX#include "nbatcher.h"
  731.  
  732. XXbatch_it ()
  733. XX{
  734. XX    struct stat    st;
  735. XX    FILE    *bfp, *afp;
  736. XX    char    fbuf[BUFSIZ], lckfile[40];
  737. XX    char    tbuf[80];
  738. XX    short    count;
  739. XX    int    c;
  740.  
  741. XX    if (chdir(BATCHDIR) < 0)
  742. XX        xerror ("can't chdir to %s\n", BATCHDIR);
  743.  
  744. XX    /* we create a lock file for two purposes,
  745. XX       first to make sure a previous nbatcher
  746. XX       didn't blowup and leave the lock file
  747. XX       laying around, and second to put the
  748. XX       remaining news article filenames when
  749. XX       we go over the max UUCP bytes and there's
  750. XX       still files remaining for batching.
  751. XX    */
  752.  
  753. XX    sprintf (lckfile, ".%s.lock", ep.site);
  754. XX    if (!access(lckfile, 0))
  755. XX        xerror ("lockfile already exists for %s\n", ep.site);
  756.  
  757. XX    if ((lfp=fopen(lckfile, "w")) == NULL)
  758. XX        xerror ("can't create lockfile for %s\n", ep.site);
  759.  
  760. XX    /* now that we've locked ourselves for this site,
  761. XX       lets carry on */
  762.  
  763. XX    if ((bfp=fopen(ep.site, "r")) == NULL)
  764. XX        xerror ("can't open %s/%s for reading\n", BATCHDIR, ep.site);
  765.  
  766. XX    if (tfile == NULL) {
  767. XX        tfile = mktemp("/tmp/bnewsXXXXXX");
  768. XX        if ((tfp=fopen(tfile, "w")) == NULL)
  769. XX            xerror ("can't open %s for writing\n", tfile);
  770. XX    }
  771.  
  772. XX    count = fcnt = scnt = 0;
  773. XX    cu_bytes = 0;
  774. XX    while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL) {
  775. XX        fbuf[strlen(fbuf)-1] = '\0';    /* remove the newline */
  776. XX        if ((afp=fopen(fbuf, "r")) == NULL) {
  777. XX           fprintf (stderr, "bypassing article %s: can't read it\n",
  778. XX                fbuf);
  779. XX            continue;
  780. XX        }
  781. XX        if (fstat (fileno(afp), &st) < 0)
  782. XX             xerror ("fstat failed on %s\n", fbuf);
  783. XX        cu_bytes += st.st_size;
  784.  
  785. XX        /* if the max byte count is exceeded,
  786. XX           save the remaining files for later */
  787.  
  788. XX        if ((cu_bytes + n_bytes) > ep.m_bytes) {
  789. XX            fprintf (lfp, "%s\n", fbuf); /* put the '\n' back */
  790. XX            while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL)
  791. XX                fputs (fbuf, lfp);
  792. XX            fclose (bfp);
  793. XX            fclose (lfp);
  794. XX            fclose (afp);
  795. XX            unlink (ep.site);
  796. XX            if (link(lckfile, ep.site) < 0)
  797. XX               xerror ("can't link lockfile to %s\n", ep.site);
  798. XX            unlink (lckfile);
  799. XX            chown (ep.site, NEWSUID, NEWSGID);
  800. XX            if (count)
  801. XX                spoolit ();
  802. XX             if (cu_bytes - st.st_size)
  803. XX                 log_it (cu_bytes - st.st_size);
  804. XX            return;
  805. XX        }
  806. XX        sprintf (tbuf, "#! rnews %ld\n", st.st_size);
  807. XX        fputs (tbuf, tfp);
  808. XX        while ((c=getc(afp)) != EOF)
  809. XX            putc (c, tfp);
  810. XX        fclose (afp);
  811.  
  812. XX        if (++count == nfiles) {
  813. XX            spoolit ();
  814. XX            count = 0;
  815. XX        }
  816. XX        fcnt++;
  817. XX    }
  818.  
  819. XX    /* The final spool if less than nfiles
  820. XX       is encountered.  The zero out the
  821. XX       batchfile and unlink the lock file */
  822.  
  823. XX    spoolit ();
  824. XX    close (creat(ep.site, 0664));
  825. XX    chown (ep.site, NEWSUID, NEWSGID);
  826. XX    unlink (lckfile);
  827.  
  828. XX    /* here we log what we've done, and
  829. XX       if vflg is set, a copy to stdout
  830. XX       as well */
  831.  
  832. XX    log_it (0);
  833. XX    if (chdir(LIBDIR) < 0)
  834. XX        xerror ("can't chdir back to %s\n", LIBDIR);
  835.  
  836. XX}
  837.  
  838. XXspoolit ()
  839. XX{
  840. XX    struct stat    st;
  841. XX    char    cmd[BUFSIZ], cfile[80];
  842. XX    FILE    *pfp;
  843. XX    int    c;
  844.  
  845. XX    fclose (tfp);
  846. XX    stat (tfile, &st);
  847.  
  848. XX    /* if for some reason the temp file
  849. XX       is zero, just return */
  850.  
  851. XX    if (st.st_size == 0)
  852. XX        return;
  853.  
  854. XX    /* if ep.c_bits is set use COMPRESS to compress
  855. XX       the temp file first
  856. XX    */
  857.  
  858. XX    if (ep.c_bits) {
  859. XX        sprintf (cmd, "%s -b%d %s", COMPRESS, ep.c_bits, tfile);
  860. XX        if (system(cmd) != 0)
  861. XX            xerror ("system(%s) failed\n", cmd);
  862.  
  863. XX        strcpy (cfile, tfile);
  864. XX        strcat (cfile, ".Z");
  865. XX        if ((tfp=fopen(cfile, "r")) == NULL)
  866. XX            xerror ("can't open %s for reading\n", cfile);
  867.  
  868. XX        /* if ep.command has a specific command
  869. XX           for UUCP spooling, use it.  If not,
  870. XX           use UUX.
  871. XX        */
  872.  
  873. XX        if (ep.command[0] != '\0')
  874. XX            strcpy (cmd, ep.command);
  875. XX        else
  876. XX            sprintf (cmd, "%s %s!rnews", UUX, ep.site);
  877.  
  878. XX        /* now popen the command for writing
  879. XX           and send it the contents of tempfile */
  880.  
  881. XX        if ((pfp=popen(cmd, "w")) == NULL)
  882. XX            xerror ("popen failed on %s\n", cmd);
  883.  
  884. XX        /********************************************
  885. XX         * for version 2.10.3 and above,
  886. XX         * prepend `#! cunbatch'.
  887. XX         *
  888. XX         * NOTE: The remote site MUST be able to
  889. XX         *       except this format, or it will
  890. XX         *       be lost!!!
  891. XX         *******************************************/
  892.  
  893. XX        fputs ("#! cunbatch\n", pfp);
  894. XX        while ((c=getc(tfp)) !=  EOF)
  895. XX            putc (c, pfp);
  896.  
  897. XX        pclose (pfp);
  898. XX        fclose (tfp);
  899. XX        unlink (cfile);
  900. XX    } else {            /* regular batching here */
  901. XX        if ((tfp=fopen(tfile, "r")) == NULL)
  902. XX            xerror ("can't open %s for reading\n", tfile);
  903.  
  904. XX        /* if ep.command has a specific command
  905. XX           for UUCP spooling, use it.  If not,
  906. XX           use UUX.
  907. XX        */
  908.  
  909. XX        if (ep.command[0] != '\0')
  910. XX            strcpy (cmd, ep.command);
  911. XX        else
  912. XX            sprintf (cmd, "%s %s!rnews", UUX, ep.site);
  913.  
  914. XX        if ((pfp=popen(cmd, "w")) == NULL)
  915. XX            xerror ("popen failed on %s\n", cmd);
  916.  
  917. XX        while ((c=getc(tfp)) != EOF)
  918. XX            putc (c, pfp);
  919.  
  920. XX        pclose (pfp);
  921. XX        fclose (tfp);
  922. XX    }
  923. XX    if ((tfp=fopen(tfile, "w")) == NULL)
  924. XX        xerror ("can't re-open %s\n", tfile);
  925.  
  926. XX    scnt++;
  927. XX}
  928. @//E*O*F nbatcher.c//
  929. chmod u=rw,g=rw,o=rw nbatcher.c
  930.  
  931. echo x - parse.c
  932. sed 's/^XX//' > "parse.c" <<'@//E*O*F parse.c//'
  933. XX/*
  934. XX *
  935. XX *    parse.c - nbatcher line parser for the control file
  936. XX *
  937. XX *
  938. XX *    R.J. Esposito
  939. XX *    Bell of Penna.
  940. XX *    June 1986
  941. XX *
  942. XX */
  943.  
  944. XX#include <stdio.h>
  945. XX#include <sys/types.h>
  946. XX#include <ctype.h>
  947. XX#include "nbatcher.h"
  948.  
  949. XX#define MAX_BYTES    1000000L    /* max allowable bytes */
  950.  
  951. XXparse_entry (line)
  952. XXchar *line;
  953. XX{
  954. XX    register char    *p;
  955. XX    short    num, upper;
  956. XX    short    lower, dash;
  957. XX    long    l_num;
  958.  
  959. XX    upper = 23;    /* upper hour limit */
  960. XX    lower = 0;    /* lower hour limit */
  961. XX    dash = 0;
  962.  
  963. XX    clear_entry (&ep);    /* zero out the structure */
  964.  
  965. XX    p = (char *) ep.site;
  966.  
  967. XX    /* get the site name and copy
  968. XX       it to the structure */
  969.  
  970. XX    while (*line && *line != COLON)
  971. XX        *p++ = *line++;
  972. XX    *p = '\0';
  973. XX    if (*++line == '\n' || *line == '\0')
  974. XX        xerror ("illegal number of fields\n");
  975.  
  976. XX    /* check that its valid */
  977.  
  978. XX    if (ep.site[0] == '\0')
  979. XX        xerror ("null site name in control file\n");
  980.  
  981. XX    /* now, parse the hour string and check
  982. XX       for valid syntax */
  983.  
  984. XX    p = (char *) ep.hour;
  985. XX    while (*line && *line != COLON)
  986. XX        *p++ = *line++;
  987.  
  988. XX    *p = '\0';
  989. XX    if (*++line == '\n' || *line == '\0')
  990. XX        xerror ("illegal number of fields\n");
  991.  
  992. XX    if (ep.hour[0] == '\0')
  993. XX        xerror ("null hour string in control file\n");
  994.  
  995. XX    /* now re-scan the hour in structure and
  996. XX       weed out the badies */
  997.  
  998. XX    if (ep.hour[0] == '*' && ep.hour[1] != '\0')
  999. XX        xerror ("invalid hour string syntax: %s\n", ep.hour);
  1000. XX    else if (ep.hour[0] == '*')
  1001. XX        goto h_skip;
  1002.  
  1003. XX    if (strcmp(ep.hour, "off", 3) == 0 && ep.hour[3] != '\0')
  1004. XX        xerror ("invalid hour string syntax: %s\n", ep.hour);
  1005. XX    else if (strncmp(ep.hour, "off", 3) == 0)
  1006. XX        goto h_skip;
  1007.  
  1008. XX    p = (char *) ep.hour;
  1009. XX    if (!isdigit(*p))
  1010. XX        xerror ("non-numeric char in hour string: %c\n", *p);
  1011.  
  1012. XX    while (*p) {
  1013. XX        num = 0;
  1014. XX        do {
  1015. XX            num = num*10 + (*p - '0');
  1016. XX        } while (isdigit(*++p));
  1017.  
  1018. XX        if (num < lower || num > upper)
  1019. XX            xerror ("illegal hour: %d\n", num);
  1020.  
  1021. XX        if (!*p)
  1022. XX            break;
  1023.  
  1024. XX        if (*p == '-' && dash)
  1025. XX            xerror ("syntax error in hour field\n");
  1026. XX        else if (*p == '-')
  1027. XX            dash = TRUE;
  1028.  
  1029. XX        if (*p != ',' && *p != '-')
  1030. XX            xerror ("non-numeric char in hour string: %c\n", *p);
  1031. XX        else if (!isdigit(*++p))
  1032. XX            xerror ("syntax error in hour field\n");
  1033.  
  1034. XX    }
  1035.  
  1036. XX    /* now that thats over with, let do the compression
  1037. XX       field.  Only 9-16 is allowed, except a null field
  1038. XX       indicates no compression for this site. */
  1039.  
  1040. XXh_skip:
  1041. XX    num = 0;
  1042. XX    while (*line && *line != COLON) {
  1043. XX        if (!isdigit(*line))
  1044. XX            xerror ("non-numeric in compression field\n");
  1045. XX        num = num*10 + (*line++ - '0');
  1046. XX    }
  1047. XX    if (*++line == '\n' || *line == '\0')
  1048. XX        xerror ("illegal number of fields\n");
  1049.  
  1050. XX    if (num != 0 && (num < 9 || num > 16))
  1051. XX        xerror ("illegal compression bits: %d\n", num);
  1052.  
  1053. XX    ep.c_bits = num;
  1054.  
  1055. XX    /* now check the max. bytes for UUCP queue.
  1056. XX       Note: There is a max. allowable # of bytes
  1057. XX         here, set at 1MB.  Change it at your
  1058. XX         own risk.
  1059. XX    */
  1060.  
  1061. XX    l_num = 0;
  1062. XX    while (*line && *line != COLON) {
  1063. XX        if (!isdigit(*line))
  1064. XX            xerror ("non-numeric in max. bytes field\n");
  1065.  
  1066. XX        l_num = l_num*10 + (*line++ - '0');
  1067. XX    }
  1068.  
  1069. XX    if (l_num > MAX_BYTES)
  1070. XX        xerror ("%ld max. bytes exceeds allowable maximun\n", l_num);
  1071.  
  1072. XX    if (l_num != 0)
  1073. XX        ep.m_bytes = l_num;
  1074. XX    else
  1075. XX        ep.m_bytes = DFL_BYTES;
  1076.  
  1077. XX    /* and finally the command line (if there is one) */
  1078.  
  1079. XX    p = (char *) ep.command;
  1080.  
  1081. XX    if (*++line != '\n' && *line != '\0') {
  1082. XX        while (*line && *line != '\n')
  1083. XX            *p++ = *line++;
  1084.  
  1085. XX        *p = '\0';
  1086. XX    }
  1087. XX}
  1088.  
  1089. XX#ifdef USE_PORT_CODE
  1090. XXxerror (fmt, a1, a2)
  1091. XXchar *fmt;
  1092. XXchar *a1, *a2;
  1093. XX{
  1094. XX    char    buf[BUFSIZ];
  1095.  
  1096. XX    sprintf (buf, fmt, a1, a2);
  1097. XX    printf ("nbatcher: %s\n", fmt);
  1098. XX    exit (99);
  1099. XX}
  1100.  
  1101. XX#else
  1102. XXxerror (fmt, argp)
  1103. XXchar *fmt;
  1104. XXint argp;
  1105. XX{
  1106. XX    char    buf[BUFSIZ];
  1107. XX    char    fbuf[BUFSIZ];
  1108. XX    FILE    prwbuf;
  1109. XX    register char    *cp;
  1110. XX    
  1111. XX    prwbuf._flag = _IOWRT;
  1112. XX    prwbuf._file = _NFILE;
  1113. XX    prwbuf._cnt = 32767;
  1114. XX    prwbuf._ptr = (unsigned char *)buf;
  1115. XX    prwbuf._base = (unsigned char *)buf;
  1116. XX    sprintf (fbuf, "%s: %s", "nbatcher", fmt);
  1117. XX    _doprnt (fbuf, (char *)&argp, &prwbuf);
  1118. XX    putc ('\0', &prwbuf);
  1119. XX    for (cp = buf; *cp != '\0'; cp++)
  1120. XX        putchar (*cp);
  1121.  
  1122. XX    exit (99);
  1123. XX}
  1124. XX#endif    /* USE_PORT_CODE */
  1125.  
  1126. XXclear_entry (s)
  1127. XXchar *s;
  1128. XX{
  1129. XX    register int i;
  1130.  
  1131. XX    for (i=0; i<sizeof(struct file_entry); *s++ = '\0', i++)
  1132. XX                ;
  1133.  
  1134. XX}
  1135. @//E*O*F parse.c//
  1136. chmod u=rw,g=rw,o=rw parse.c
  1137.  
  1138. echo Inspecting for damage in transit...
  1139. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  1140. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  1141. cat > $temp <<\!!!
  1142.       60     480    3043 README
  1143.       76     441    2526 nbatcher.1
  1144.       14      88     459 nbatcher.ctl
  1145.       81     678    3907 nbatcher.doc
  1146.       67     185    1387 Makefile
  1147.       61     159    1088 bst.c
  1148.      155     501    3094 checkwork.c
  1149.       27      52     284 define.c
  1150.       50     148    1022 logger.c
  1151.       47     103     699 main.c
  1152.      212     696    4805 nbatcher.c
  1153.      202     668    4011 parse.c
  1154.     1052    4199   26325 total
  1155. !!!
  1156. wc  README nbatcher.1 nbatcher.ctl nbatcher.doc Makefile bst.c checkwork.c define.c logger.c main.c nbatcher.c parse.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  1157. if test -s $dtemp
  1158. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  1159. else echo "No problems found."
  1160. fi
  1161. exit 0
  1162.